1 00:00:00,480 --> 00:00:01,080 Hey there. 2 00:00:01,080 --> 00:00:01,980 Welcome back. 3 00:00:01,980 --> 00:00:07,170 We're going to jump right into this lecture by starting to script our admin handler on the server. 4 00:00:07,170 --> 00:00:11,910 The purpose of this script is to check for when players either type commands in their chat, or use 5 00:00:11,910 --> 00:00:15,150 their GUIs to fire an event to execute commands. 6 00:00:15,150 --> 00:00:16,800 So let's go ahead and get started. 7 00:00:16,800 --> 00:00:19,950 Inside of the script we're going to need four services. 8 00:00:19,950 --> 00:00:22,140 One is going to be the player service. 9 00:00:22,320 --> 00:00:27,660 That way we can get access to players that join our game and set up any functionality for their chat 10 00:00:27,660 --> 00:00:28,500 events. 11 00:00:28,500 --> 00:00:31,410 And then we're going to need replicated storage as well. 12 00:00:34,100 --> 00:00:39,830 We're going to need the data store service, and we're going to use this to store any players we want 13 00:00:39,830 --> 00:00:43,520 to add into the data store to become permanent admins in our game. 14 00:00:44,180 --> 00:00:49,280 And then we're also going to need the run service and you'll see why in a moment. 15 00:00:50,000 --> 00:00:53,210 Now inside of our variable section we're going to create a new data store. 16 00:00:53,210 --> 00:00:56,570 I'm just going to call it Admin data store. 17 00:00:57,390 --> 00:01:02,550 Now we're going to refer to our data store service and use the Get Data Store function to either get 18 00:01:02,550 --> 00:01:05,280 or create a new data store if it doesn't exist. 19 00:01:05,280 --> 00:01:08,910 And we're just going to call this data store admin ranks. 20 00:01:10,780 --> 00:01:15,910 And then from this point, we need to refer to all of the other assets we have in replicated stores. 21 00:01:15,940 --> 00:01:18,130 So first I'm going to make a reference to the folder. 22 00:01:18,130 --> 00:01:22,390 I'll just call it admin assets equal to Replicated Storage and get that folder. 23 00:01:22,570 --> 00:01:26,440 And then we can get, you know the request event that's inside of there. 24 00:01:26,440 --> 00:01:30,220 So admin assets dot request get that remote function. 25 00:01:30,340 --> 00:01:34,480 We'll have one for communicating between the client and server. 26 00:01:35,960 --> 00:01:40,580 And then we'll also have one for communicating between different server scripts. 27 00:01:40,580 --> 00:01:44,570 So we're going to be using our commands module script to execute commands. 28 00:01:44,570 --> 00:01:50,240 And sometimes this module script may need to communicate back with the main script that required it. 29 00:01:50,240 --> 00:01:52,640 So that's what we're going to use that Bindable for. 30 00:01:56,020 --> 00:01:59,650 And then we're also going to require all of the different module scripts we have. 31 00:01:59,650 --> 00:02:02,710 So first we need to require our admin settings. 32 00:02:02,710 --> 00:02:05,380 So require inside of our admin assets. 33 00:02:05,410 --> 00:02:10,930 Get settings will require our admin enum as well. 34 00:02:15,680 --> 00:02:18,110 And we're also going to require our commands. 35 00:02:18,110 --> 00:02:19,490 Module script. 36 00:02:23,470 --> 00:02:27,730 And then I'm also going to make a reference to the guy that is inside of that folder. 37 00:02:27,730 --> 00:02:32,500 So inside of our admin assets we have our guy for admin. 38 00:02:32,500 --> 00:02:38,290 So I'll just call this admin guy and we'll refer to that inside of that folder. 39 00:02:39,770 --> 00:02:45,620 The last thing I want to keep track of is I want to keep track of all of the functions that are connected 40 00:02:45,620 --> 00:02:47,090 to different players. 41 00:02:47,120 --> 00:02:48,500 Uh, chat events. 42 00:02:48,500 --> 00:02:52,610 So different player objects have an event called chatted or I believe it's chat. 43 00:02:52,610 --> 00:02:59,270 And sometimes we may want to disconnect those functions that are attached to each of those players event. 44 00:02:59,270 --> 00:03:04,970 In the case that maybe we un admin them, or we add new admin and then remove it later or something 45 00:03:04,970 --> 00:03:05,510 like that. 46 00:03:05,510 --> 00:03:08,300 So we can store all of those connections in a table. 47 00:03:08,300 --> 00:03:10,190 And we're just going to call it connections. 48 00:03:10,550 --> 00:03:16,370 Now some of the functions we're going to need are we're actually one we'll need is we're going to have 49 00:03:16,370 --> 00:03:20,150 to steal this one we created inside of our commands module script. 50 00:03:20,150 --> 00:03:26,600 So we're going to use that here as well I want to have a function for getting the rank of a player that 51 00:03:26,600 --> 00:03:27,500 is in our game. 52 00:03:27,500 --> 00:03:33,170 So we'll pass a player object to this function and it'll return back to us a number that represents 53 00:03:33,170 --> 00:03:34,190 their rank. 54 00:03:34,640 --> 00:03:40,370 I also want to have a function and I'm going to call it get player from string. 55 00:03:40,370 --> 00:03:43,850 And this function will will pass. 56 00:03:43,850 --> 00:03:47,030 Somebody called a caller the person who called this function. 57 00:03:47,030 --> 00:03:48,440 And that's going to be a player. 58 00:03:48,440 --> 00:03:51,200 And then we're also going to have a string in here. 59 00:03:51,990 --> 00:03:59,100 And this function is either going to return an empty table or a table with player objects inside of 60 00:03:59,100 --> 00:03:59,520 it. 61 00:03:59,550 --> 00:04:06,330 So the purpose of this function is that let's say a player uses a command and we need to get a player 62 00:04:06,330 --> 00:04:07,110 for that command. 63 00:04:07,110 --> 00:04:11,910 So let's say they use the word like me or they use the word others or all. 64 00:04:11,910 --> 00:04:14,700 We either need to get just the player itself. 65 00:04:14,700 --> 00:04:20,760 We either need to get every other player in the game besides the caller, or we need to get every single 66 00:04:20,760 --> 00:04:23,100 player in the game or a specific player. 67 00:04:23,100 --> 00:04:25,260 And that's going to be the purpose of this function. 68 00:04:25,680 --> 00:04:29,310 The next function we'll need is to execute a command. 69 00:04:29,490 --> 00:04:31,980 And this function will take a player. 70 00:04:31,980 --> 00:04:34,950 So the person who is executing the function. 71 00:04:34,950 --> 00:04:41,070 And we're going to get the message they sent to us either in chat or through an event. 72 00:04:41,070 --> 00:04:45,960 And this is going to take that message and split it up into its different components. 73 00:04:45,960 --> 00:04:52,590 So if they do a command like kill others, then it'll split up the message into kill and then others. 74 00:04:52,590 --> 00:04:57,780 And then based on that, we're going to extract information, uh, based on the different parameters 75 00:04:57,780 --> 00:04:59,190 for a command. 76 00:04:59,640 --> 00:05:03,360 And this function can also return either a boolean. 77 00:05:03,960 --> 00:05:05,940 And a string possibly. 78 00:05:05,940 --> 00:05:12,810 So we'll have this function either return true, or if we encountered a problem trying to execute a 79 00:05:12,810 --> 00:05:16,620 command, we'll do return false and some error message. 80 00:05:17,100 --> 00:05:18,870 So we'll do something like that. 81 00:05:19,940 --> 00:05:24,590 The next function we'll need is for removing admin from a player. 82 00:05:24,590 --> 00:05:28,730 So we'll just call it remove admin from and we'll pass a player to this. 83 00:05:30,070 --> 00:05:34,930 And then we'll need a function to set up admin or give admin to a player. 84 00:05:34,930 --> 00:05:38,260 So we'll call it um setup admin for. 85 00:05:38,260 --> 00:05:41,350 And again we'll pass a player object to this function. 86 00:05:42,440 --> 00:05:48,950 Now, some of the different events we're going to need to listen to are going to be when a player gets 87 00:05:48,950 --> 00:05:50,450 added into our game. 88 00:05:50,450 --> 00:05:55,400 So the player added event, we're going to connect a function to this and get that player. 89 00:05:56,230 --> 00:06:01,780 And depending on whether or not this player is an admin, we can try to set up admin for them. 90 00:06:02,230 --> 00:06:07,030 Um, we're going to need to listen to our request remote function. 91 00:06:07,030 --> 00:06:11,590 So on server invoke we're going to set it equal to a new lambda function. 92 00:06:11,800 --> 00:06:17,440 And we're going to kind of set it up like we've done in the past, where we have the player that has 93 00:06:17,440 --> 00:06:18,940 called this function. 94 00:06:18,940 --> 00:06:21,340 They're giving us an action to do. 95 00:06:21,340 --> 00:06:22,690 So that's going to be a string. 96 00:06:22,690 --> 00:06:25,750 And they're passing any other arguments to go with that action. 97 00:06:26,200 --> 00:06:29,710 And then we're also going to listen to our coms Bindable. 98 00:06:30,400 --> 00:06:34,390 On invoke and again set it up with a lambda function. 99 00:06:34,390 --> 00:06:39,340 And since this is not a remote function, we don't get a player object. 100 00:06:39,340 --> 00:06:43,120 Instead we just get the action and the arguments for that action. 101 00:06:44,060 --> 00:06:44,660 All right. 102 00:06:44,660 --> 00:06:45,770 We've got everything set up. 103 00:06:45,770 --> 00:06:48,980 So let's go ahead and start filling out these different sections. 104 00:06:48,980 --> 00:06:55,010 So inside of the git rank function we need to be able to determine the rank of a player that we pass 105 00:06:55,010 --> 00:06:56,210 to this function. 106 00:06:56,210 --> 00:07:02,000 Now since we are going to be storing all of the players IDs as a string. 107 00:07:02,000 --> 00:07:06,560 So let me go to the settings, since their id is going to be stored as a string. 108 00:07:06,560 --> 00:07:12,920 That way we set up these tables as dictionaries and we do not set them up as arrays. 109 00:07:13,040 --> 00:07:15,590 Then we need to create a key for this player. 110 00:07:15,590 --> 00:07:17,060 So I'm going to call it key. 111 00:07:17,360 --> 00:07:22,550 And we're going to use the two string function to convert their user ID into a string. 112 00:07:23,290 --> 00:07:27,250 And then from this point, we can use this key to check whether or not they have a rank. 113 00:07:27,250 --> 00:07:29,650 So I'm going to create a variable called rank. 114 00:07:29,770 --> 00:07:31,930 And we're going to set it equal to. 115 00:07:32,020 --> 00:07:38,950 We're going to first check the admin settings dot player ranks to see if the player exists within our 116 00:07:38,950 --> 00:07:41,260 hard coded table here. 117 00:07:41,650 --> 00:07:51,700 So if they have this rank in here or we could check if they exist within the temporary mods table, 118 00:07:51,700 --> 00:07:53,140 pass the key as well. 119 00:07:53,950 --> 00:07:59,260 So we're going to get that rank and then we can check, um, if there is no rank. 120 00:07:59,260 --> 00:08:04,600 So they weren't stored in the player ranks table or the temporary mods table, then we should check 121 00:08:04,600 --> 00:08:06,190 the data store. 122 00:08:06,190 --> 00:08:10,540 However, I only want to do this on an actual server. 123 00:08:10,540 --> 00:08:16,540 So if you're testing your game out in studio, uh, you don't really want to mess with data stores at 124 00:08:16,540 --> 00:08:17,560 all in studio. 125 00:08:17,560 --> 00:08:22,120 So that's why we need the run service in here, to make sure that we're not running in studio so we 126 00:08:22,120 --> 00:08:25,840 can do and not run service is studio. 127 00:08:25,840 --> 00:08:34,270 So if we're not running in studio, then we can, uh, call a function in our data store to get any 128 00:08:34,270 --> 00:08:35,830 data for this particular player. 129 00:08:35,830 --> 00:08:41,440 And of course, since a data store is going to be interacting with the cloud, we need to wrap it in 130 00:08:41,440 --> 00:08:43,930 a call function in case it errors. 131 00:08:43,930 --> 00:08:49,780 So we can create two variables, one called success and result equal to the p call function. 132 00:08:49,780 --> 00:08:54,340 And in here we're going to pass the admin data store. 133 00:08:54,340 --> 00:08:57,910 And the function we want to use is the get async function. 134 00:08:58,210 --> 00:09:02,620 And then we need to pass any other information to this particular function. 135 00:09:02,620 --> 00:09:03,910 Now you need to know something. 136 00:09:03,910 --> 00:09:11,440 When we use our admin data store admin data store the function get async uses a colon. 137 00:09:11,440 --> 00:09:13,180 And what do we know about using colons? 138 00:09:13,180 --> 00:09:18,790 Well that means the data store itself gets automatically passed to the function as self. 139 00:09:19,030 --> 00:09:24,160 So that means the first argument we need to pass to this function is the data store itself. 140 00:09:24,160 --> 00:09:25,390 So admin data store. 141 00:09:25,390 --> 00:09:29,560 That is the first argument we have to pass to this function. 142 00:09:29,560 --> 00:09:32,770 And then the second argument we can pass is just the key. 143 00:09:33,040 --> 00:09:38,440 So this is basically doing the exact same thing as this is doing right here. 144 00:09:38,440 --> 00:09:41,470 But we're just wrapping it in a p call in case it errors. 145 00:09:41,470 --> 00:09:44,890 So maybe their server is down or some internet error happens. 146 00:09:44,890 --> 00:09:45,460 Whatever. 147 00:09:45,460 --> 00:09:49,000 We just got to make sure to wrap it in a protected call function. 148 00:09:49,540 --> 00:09:52,390 After that we can check if we were successful. 149 00:09:52,390 --> 00:09:57,820 So if success, then what we could do is we could set rank equal to the result and that's it. 150 00:09:59,500 --> 00:10:06,160 And then at the very end here, what we could do is we can return, uh, if rank, then we'll just return 151 00:10:06,160 --> 00:10:06,730 rank. 152 00:10:07,120 --> 00:10:09,220 Otherwise we're going to return zero. 153 00:10:09,220 --> 00:10:15,340 So let's say they didn't have a rank in these tables and they don't have a rank in the data store. 154 00:10:15,340 --> 00:10:18,370 Well that means they are a non-admin. 155 00:10:18,370 --> 00:10:20,170 So we should return zero. 156 00:10:20,170 --> 00:10:24,670 Otherwise if we did get a result from either of these tables or the data store, then we're going to 157 00:10:24,670 --> 00:10:26,860 return that rank back in this function. 158 00:10:27,650 --> 00:10:28,190 Okay. 159 00:10:28,190 --> 00:10:31,970 So let's go ahead and start filling out our guitar player from string function. 160 00:10:32,120 --> 00:10:38,900 So the first thing I want to do is I want to check, uh, whether or not the string is going to be equal 161 00:10:38,900 --> 00:10:40,580 to different elements. 162 00:10:40,580 --> 00:10:45,830 So if the string and we're going to call the lower function on it to make it all lowercase, that way 163 00:10:45,830 --> 00:10:53,630 we can, uh, you know, stay consistent because in case somebody types capitals like capital M or capital 164 00:10:53,630 --> 00:11:00,530 others like maybe they do this or they do this, we want to lowercase it to make it, you know, easy 165 00:11:00,530 --> 00:11:02,180 to recognize in our script. 166 00:11:02,180 --> 00:11:04,970 So if the string is equal to me. 167 00:11:06,450 --> 00:11:13,860 Then we can just return a new table with the caller of this function inside of it. 168 00:11:13,860 --> 00:11:18,210 So it just returns the player back to where this function was called. 169 00:11:18,240 --> 00:11:27,210 Otherwise, if this string is equal to something like all, then we can just return a table from players 170 00:11:27,210 --> 00:11:29,490 and we just get all of the players in the game. 171 00:11:30,720 --> 00:11:35,640 If the string is equal to others. 172 00:11:36,540 --> 00:11:43,800 Then what we could do is we could create a table, call it others, and we'll use players, get players. 173 00:11:44,680 --> 00:11:52,090 And remember, we need to remove the collar out of this table so we can do table dot remove inside of 174 00:11:52,090 --> 00:11:53,230 others. 175 00:11:53,680 --> 00:11:55,900 And we want to remove at the index. 176 00:11:55,900 --> 00:12:02,500 We're going to use the table dot find function to find uh where the player is stored in this table. 177 00:12:02,500 --> 00:12:03,640 So others. 178 00:12:04,570 --> 00:12:10,840 Collar, so it's going to return back to us a number wherever our collar is stored in this table. 179 00:12:10,840 --> 00:12:17,560 And then we remove it out of our others table, and then we can just return that otherwise. 180 00:12:18,270 --> 00:12:23,070 If they didn't put me all or others, then that means we need to search for a particular player in our 181 00:12:23,070 --> 00:12:23,700 game. 182 00:12:23,970 --> 00:12:30,660 So the first thing we can do is we can create a variable called player, and we'll set it equal to players. 183 00:12:30,660 --> 00:12:35,250 And we're going to find first child with the string. 184 00:12:36,040 --> 00:12:41,230 Now that's probably not going to work unless they type their name out perfectly. 185 00:12:41,230 --> 00:12:48,310 So in case we do not have a player, then what we need to do is we need to loop through every single 186 00:12:48,310 --> 00:12:52,720 player inside of players, get players. 187 00:12:52,720 --> 00:12:55,600 So we got to go through every single player in our game. 188 00:12:55,600 --> 00:12:58,810 And what we need to do is we need to check if their name. 189 00:12:59,400 --> 00:13:02,220 And we're going to get a substring of their name. 190 00:13:02,220 --> 00:13:04,980 So we're going to use the sub function. 191 00:13:06,160 --> 00:13:12,580 And we're going to start at the index of one and go all the way to the max length of our string that 192 00:13:12,580 --> 00:13:14,080 was passed to this function. 193 00:13:14,960 --> 00:13:17,660 And then we also got to make sure to set it to lowercase. 194 00:13:17,990 --> 00:13:23,690 So if all of that is not equal to our string. 195 00:13:24,640 --> 00:13:26,470 Then we're just going to continue looping. 196 00:13:26,470 --> 00:13:34,810 So what this is doing is let's say we do something like kill uh c right. 197 00:13:34,810 --> 00:13:37,240 Let's say they only put the letter C. 198 00:13:37,240 --> 00:13:42,520 Well, what this is going to do is it's going to loop through every single player in our game, and 199 00:13:42,520 --> 00:13:48,040 it's going to find the first player whose name starts with C, because we're getting a substring here. 200 00:13:48,040 --> 00:13:54,730 So this will only store the string of C because the length of our string is only one character. 201 00:13:54,970 --> 00:13:59,860 So if we do find a match then we can just set player equal to player. 202 00:13:59,860 --> 00:14:09,970 And then once this loop is over then we can go ahead and return player inside of a new table. 203 00:14:09,970 --> 00:14:15,250 However, we only want to return that if the player actually exists in our game. 204 00:14:15,870 --> 00:14:20,640 So if there is a player with this particular name in our game, then we're going to return a table with 205 00:14:20,640 --> 00:14:21,660 them inside of it. 206 00:14:21,720 --> 00:14:26,850 Otherwise, if we make it through all of that and we couldn't find a player at all, then we can just 207 00:14:26,850 --> 00:14:28,500 return an empty table. 208 00:14:29,310 --> 00:14:32,790 All right, so now let's get into our fun little function here. 209 00:14:32,790 --> 00:14:35,370 And that's going to be executing commands. 210 00:14:35,550 --> 00:14:40,650 So the purpose of this function is we're going to pass a player to it the person who's executing the 211 00:14:40,650 --> 00:14:42,720 command and their message. 212 00:14:42,720 --> 00:14:47,820 So for example they might type out something like set speed. 213 00:14:47,850 --> 00:14:51,090 Others 140. 214 00:14:51,090 --> 00:14:57,030 And what we need to do is we need to split up this string into different sections or arguments. 215 00:14:57,030 --> 00:15:03,780 So one section needs to be the command, one section needs to be the first argument to this command, 216 00:15:03,780 --> 00:15:07,920 and the second will be the second argument, and so on and so on. 217 00:15:07,920 --> 00:15:12,540 If they have, you know, more parameters or arguments for this particular command. 218 00:15:12,540 --> 00:15:14,760 And that's actually very easy to do. 219 00:15:14,760 --> 00:15:18,540 And what we could do is we can create a table, I'm going to call it ARGs. 220 00:15:18,540 --> 00:15:22,110 And we're going to use a function in the string library called split. 221 00:15:22,110 --> 00:15:27,660 And what this does is it says right here splits a string into parts based on the defined separator. 222 00:15:27,660 --> 00:15:30,030 And what's going to be our defined separator. 223 00:15:30,030 --> 00:15:32,040 Well that's going to be a space. 224 00:15:32,040 --> 00:15:35,970 Because if they do a command like set speed others. 225 00:15:37,360 --> 00:15:40,690 The only thing separating each of these strings here is a space. 226 00:15:40,690 --> 00:15:43,300 So we want to split it up based on the space. 227 00:15:43,300 --> 00:15:43,990 And that's very easy. 228 00:15:43,990 --> 00:15:46,420 So we can just pass the string here. 229 00:15:46,420 --> 00:15:51,100 So the message and we want to split it up based on a space. 230 00:15:51,100 --> 00:15:56,800 So now that means our argument table is going to be split up into a bunch of different strings. 231 00:15:56,800 --> 00:16:04,810 Now since we're going to be, uh, connecting this function to whenever a player chats, not everything 232 00:16:04,810 --> 00:16:08,170 that comes out of when a player chats is a command, right? 233 00:16:08,170 --> 00:16:11,260 They might say hello or hi, and it might not be a command. 234 00:16:11,260 --> 00:16:18,550 So we need to first verify that they're using the prefix that we defined inside of our settings module 235 00:16:18,550 --> 00:16:19,240 script. 236 00:16:19,240 --> 00:16:25,450 So what we can do is we can check if we're going to use the string sub function. 237 00:16:25,780 --> 00:16:27,820 And we're going to get args one. 238 00:16:27,820 --> 00:16:37,510 So we're getting a substring of the first argument from the first index to the admin settings. 239 00:16:38,280 --> 00:16:38,580 Oops. 240 00:16:38,610 --> 00:16:42,810 Admin settings get the prefix and get its length. 241 00:16:43,170 --> 00:16:45,750 So we're basically just getting the first character. 242 00:16:46,230 --> 00:16:51,840 And actually I think we need to use the length function not the hashtag function. 243 00:16:51,840 --> 00:16:52,620 So there we go. 244 00:16:52,620 --> 00:16:56,670 So this returns to us the length of the prefix which will just be one. 245 00:16:56,670 --> 00:17:00,570 So we're going to get a substring of whatever they type. 246 00:17:00,570 --> 00:17:05,820 So if they type something like this then it'll give us this prefix here. 247 00:17:05,820 --> 00:17:10,020 Or if they type something like that it'll just give us the first character. 248 00:17:10,440 --> 00:17:18,750 So if this first character is not equal to our admin settings dot prefix, then we're going to return 249 00:17:18,750 --> 00:17:19,770 false. 250 00:17:19,830 --> 00:17:25,020 And we'll give them a message like missing prefix or something like that. 251 00:17:25,800 --> 00:17:30,990 The next thing we need to do is we need to verify the usage for the command. 252 00:17:30,990 --> 00:17:35,850 So usage is going to be equal to string dot sub. 253 00:17:36,540 --> 00:17:40,590 And we're going to do args one. 254 00:17:40,800 --> 00:17:45,900 And we're going to start at the second index because we don't want to include the prefix. 255 00:17:45,900 --> 00:17:48,210 And then we can just leave Jay blank. 256 00:17:48,210 --> 00:17:50,760 That means it's going to default to negative one. 257 00:17:50,760 --> 00:17:52,920 So we're getting a substring like this. 258 00:17:52,920 --> 00:17:55,260 So somebody types set speed. 259 00:17:55,290 --> 00:18:00,870 Then what this function is going to do is it's going to get a substring of that which will just be set 260 00:18:00,870 --> 00:18:01,500 speed. 261 00:18:01,500 --> 00:18:04,230 It just gets rid of the prefix for us. 262 00:18:04,890 --> 00:18:07,770 And we'll lowercase it as well to make it easier. 263 00:18:07,800 --> 00:18:14,610 And then what we could do is we could look to see if this command exists within the available commands 264 00:18:14,610 --> 00:18:15,300 in our game. 265 00:18:15,300 --> 00:18:18,120 So I'm going to create a variable called command. 266 00:18:18,120 --> 00:18:26,460 And we're going to loop through every single command and pairs commands dot current commands. 267 00:18:27,550 --> 00:18:33,070 So we're going to loop through every single command inside of our current commands table, and we're 268 00:18:33,070 --> 00:18:36,400 going to check to see if we can find this usage. 269 00:18:37,040 --> 00:18:39,110 Inside of any of the commands in our game. 270 00:18:39,110 --> 00:18:46,790 So if table dot find inside of this command and get the usage table and we find this usage, then we 271 00:18:46,790 --> 00:18:49,010 can just set command equal to command. 272 00:18:49,370 --> 00:18:53,960 So if they use like something like set speed, it's going to look through all of our commands in the 273 00:18:53,960 --> 00:18:54,500 game. 274 00:18:54,500 --> 00:18:59,540 It's going to look inside these different usage tables and see if that string exists for these different 275 00:18:59,540 --> 00:19:00,350 usages. 276 00:19:00,350 --> 00:19:06,950 So if I had one in here like set speed and then I had another one for speed and whatnot, if it finds 277 00:19:06,950 --> 00:19:10,190 that string within the usage table then we're going to grab this command. 278 00:19:10,930 --> 00:19:14,500 However, if we did not find any command. 279 00:19:15,410 --> 00:19:21,170 Then we can just return false and tell them that this command does not exist. 280 00:19:22,180 --> 00:19:25,030 Another thing we can use is we can use our git rank function. 281 00:19:25,030 --> 00:19:27,400 So we're going to get the rank of this player. 282 00:19:28,670 --> 00:19:35,660 And we're going to ensure that their rank is at least greater than or equal to the minimum rank. 283 00:19:35,660 --> 00:19:42,620 However, if their rank is less than the command dot minimum rank, then we need to return false and 284 00:19:42,620 --> 00:19:47,450 tell them you do not have permission to use this command. 285 00:19:48,790 --> 00:19:53,140 So if they try to use a command that only has owner privileges and they're not an owner, they won't 286 00:19:53,140 --> 00:19:54,340 be able to execute it. 287 00:19:54,370 --> 00:20:00,910 The next thing we need to verify is we need to verify that the number of arguments they passed to the 288 00:20:00,910 --> 00:20:06,040 specific function actually matches the amount of arguments that is needed for the function. 289 00:20:06,040 --> 00:20:11,800 So if you remember, we made this table called parameters and it stores all of the parameters or arguments 290 00:20:11,800 --> 00:20:15,070 that are required for the function or the command. 291 00:20:15,370 --> 00:20:20,470 And we need to verify that the player actually gave us enough arguments to execute the functionality 292 00:20:20,470 --> 00:20:21,460 for this command. 293 00:20:21,580 --> 00:20:24,730 So we need to check if the number of arguments. 294 00:20:24,730 --> 00:20:29,800 And we're going to subtract this by one, because we don't want to include the prefix and the name of 295 00:20:29,800 --> 00:20:30,670 the command. 296 00:20:31,150 --> 00:20:37,390 If this is less than the number of parameters that's required for this particular command. 297 00:20:37,390 --> 00:20:44,080 So dot parameters, then we're going to return false and say missing arguments to command. 298 00:20:45,570 --> 00:20:49,980 Otherwise, if everything checks out, then what I'm going to do is I'm going to create a table, I'll 299 00:20:49,980 --> 00:20:52,140 call it ARGs to pass. 300 00:20:52,140 --> 00:20:55,620 And these are going to be the arguments we need to pass to the function. 301 00:20:55,950 --> 00:21:04,110 And we're going to loop through every single parameter that is inside of our parameters table. 302 00:21:05,430 --> 00:21:15,270 So for every single parameter type in ipairs command dot parameters. 303 00:21:15,830 --> 00:21:17,180 What we can do. 304 00:21:17,760 --> 00:21:24,990 Is, I'm going to create a variable called arg argument to be added. 305 00:21:26,700 --> 00:21:31,290 And we're going to check the type for this particular parameter. 306 00:21:31,810 --> 00:21:36,160 So if Pram type is equal to player. 307 00:21:36,160 --> 00:21:42,070 So if they use the set speed function, obviously the first parameter type is going to be player. 308 00:21:42,070 --> 00:21:44,770 Then we need to get the player. 309 00:21:44,770 --> 00:21:51,280 So what we could do is we could set arg to be added equal to get player from string. 310 00:21:51,280 --> 00:21:57,040 And we're going to pass, uh, the player that wants to execute this function. 311 00:21:57,040 --> 00:21:59,620 And we're going to do args. 312 00:21:59,710 --> 00:22:02,950 And we're going to get I and plus one. 313 00:22:03,280 --> 00:22:05,620 And you're like well why are we adding one here. 314 00:22:05,620 --> 00:22:11,110 We need to add one because again we are ignoring the very first string that's inside of our arguments 315 00:22:11,110 --> 00:22:13,630 table, which is the prefix and the name of the command. 316 00:22:13,630 --> 00:22:14,320 We don't want that. 317 00:22:14,320 --> 00:22:18,640 We want to get the arguments and not the command name. 318 00:22:19,060 --> 00:22:22,330 However, let's say this function doesn't return us anything. 319 00:22:22,330 --> 00:22:30,730 Then what we could do is, uh, check if the number of elements in this table. 320 00:22:30,730 --> 00:22:34,690 So remember this function returns back to us a table that contains players. 321 00:22:34,690 --> 00:22:38,650 So if that table is empty, then. 322 00:22:39,610 --> 00:22:47,020 Um, what we need to do is we need to return false and tell them no players, uh, exist. 323 00:22:47,680 --> 00:22:48,490 Okay. 324 00:22:48,550 --> 00:22:55,570 The next thing we need to check is if the parameter type is equal to number. 325 00:22:55,570 --> 00:23:01,840 So if it's a number then what we need to do is we need to set arg to be added equal to. 326 00:23:01,840 --> 00:23:04,450 And then we're going to use the function two number. 327 00:23:04,750 --> 00:23:11,980 And we're going to pass args again I plus one because we need to ignore the prefix and the name of the 328 00:23:11,980 --> 00:23:12,640 command. 329 00:23:13,870 --> 00:23:14,440 Otherwise. 330 00:23:14,440 --> 00:23:19,030 If the pram type is, let's say it's a string. 331 00:23:20,370 --> 00:23:23,940 Then we need to do something a little bit different. 332 00:23:23,940 --> 00:23:30,960 And that's because let's say one of our functions is kick and we kick some player, and then we need 333 00:23:30,960 --> 00:23:33,000 to give them a message for why they got kicked. 334 00:23:33,000 --> 00:23:37,200 So they're going to type out something like you've been bad. 335 00:23:37,200 --> 00:23:42,990 Well because we use the string dot split function to split up the string based on the spaces. 336 00:23:42,990 --> 00:23:47,160 Our string of you've been bad is going to be split up. 337 00:23:47,670 --> 00:23:52,140 So that means we're going to have to retrieve the string message that they wanted. 338 00:23:52,140 --> 00:23:57,900 And that means you're also going to have to, uh, place any functions that have string. 339 00:23:57,900 --> 00:24:00,090 The string needs to be the last parameter. 340 00:24:00,090 --> 00:24:05,730 Because what we're going to do here is I'm going to create a variable called text and set it to an empty 341 00:24:05,760 --> 00:24:06,540 string. 342 00:24:08,150 --> 00:24:17,180 And what we're going to do is we're going to loop, um, starting at this index plus one, because again, 343 00:24:17,180 --> 00:24:22,130 we need to ignore the first index that's in our args table. 344 00:24:22,250 --> 00:24:26,990 And we're going to loop through every single argument in our table. 345 00:24:27,440 --> 00:24:30,770 And we're going to set text equal to itself. 346 00:24:30,770 --> 00:24:34,700 And we're going to concatenate it with a new string. 347 00:24:34,700 --> 00:24:38,360 And we're going to put a directive here which is going to be a string. 348 00:24:38,360 --> 00:24:40,190 And we're going to put a space in front of it. 349 00:24:40,190 --> 00:24:46,340 And then we're going to format the string with args n. 350 00:24:46,490 --> 00:24:48,680 So for example. 351 00:24:49,650 --> 00:24:55,500 If a player typed out a command like, uh, kick. 352 00:24:56,660 --> 00:24:59,840 Others I kicked you. 353 00:25:00,230 --> 00:25:07,490 Then what this is going to do is it's going to loop through every single argument inside of our table, 354 00:25:07,490 --> 00:25:10,820 and it's going to be starting at this index plus one. 355 00:25:10,910 --> 00:25:16,280 And since this parameter is also going to be the last one, if there was any other parameters that the 356 00:25:16,280 --> 00:25:20,750 function required, it's going to skip it as well because we're adding plus one to I. 357 00:25:20,750 --> 00:25:26,810 And that means we're going to get every single other argument inside of that table that's beyond the 358 00:25:26,810 --> 00:25:27,950 other parameters. 359 00:25:27,950 --> 00:25:35,360 So it's going to get each of these strings and it's going to stitch it to our text variable. 360 00:25:35,360 --> 00:25:38,390 And that means our message will be fixed. 361 00:25:38,390 --> 00:25:41,420 So instead of it being split up as I. 362 00:25:41,420 --> 00:25:46,460 And then another string kicked and then another string you, we're connecting them all together to be 363 00:25:46,460 --> 00:25:52,760 one cohesive message of I kicked you, and then we can set ARG to be added to this text. 364 00:25:54,410 --> 00:25:59,300 Otherwise, if this particular parameter doesn't match any of these ones that we've hardcoded here, 365 00:25:59,300 --> 00:26:06,470 then we can just set arg to be added equal to args I plus one. 366 00:26:06,740 --> 00:26:12,440 Now we're not done yet because we need to verify some things first. 367 00:26:12,470 --> 00:26:14,750 So specifically here. 368 00:26:15,350 --> 00:26:20,810 If the type of our ARG to be added that we just created. 369 00:26:21,380 --> 00:26:23,210 If it's equal to a table. 370 00:26:23,820 --> 00:26:30,450 And we don't have anything inside of check for type in our table. 371 00:26:31,450 --> 00:26:32,020 Argh! 372 00:26:32,020 --> 00:26:33,700 To be added one. 373 00:26:33,700 --> 00:26:36,460 And then we pass the parameter type. 374 00:26:36,460 --> 00:26:41,350 So if whatever is stored within our table is not equal to the parameter type we expect. 375 00:26:42,640 --> 00:26:48,340 Or let's say that the type of our ARG to be added. 376 00:26:49,790 --> 00:26:52,220 Is not equal to table. 377 00:26:53,010 --> 00:26:54,510 And. 378 00:26:55,290 --> 00:27:02,850 We do not get the argument, we expect for ARG to be added with this particular parameter type. 379 00:27:03,850 --> 00:27:05,470 Then what we could do. 380 00:27:05,470 --> 00:27:08,350 And then I'm going to indent this to make it a little clearer. 381 00:27:08,950 --> 00:27:14,380 What we could do is we could return false and give them a message like command. 382 00:27:14,380 --> 00:27:21,850 And inside of like two brackets we can place a directive, uh, this command expected. 383 00:27:22,660 --> 00:27:24,430 And put another directive here as a string. 384 00:27:24,430 --> 00:27:28,900 So expected this type for argument number. 385 00:27:28,900 --> 00:27:31,720 And we're going to put another directive that's going to be a number. 386 00:27:31,720 --> 00:27:32,830 So percentage D. 387 00:27:34,150 --> 00:27:40,150 So let's say we use a command speed and we expect a number for argument. 388 00:27:40,150 --> 00:27:41,380 Let's say number two. 389 00:27:41,380 --> 00:27:42,880 But we didn't get that. 390 00:27:42,880 --> 00:27:50,200 Then we're just going to say got put another directive got this instead. 391 00:27:51,180 --> 00:27:52,290 Bear with me here. 392 00:27:52,290 --> 00:28:01,650 And then we're going to call the format function and pass command dot name the param type. 393 00:28:02,850 --> 00:28:13,590 And then I for the number and then type of and we're going to pass args here we're going to get I and 394 00:28:13,590 --> 00:28:15,540 add one to it. 395 00:28:16,160 --> 00:28:17,570 Okay, so what is this? 396 00:28:17,570 --> 00:28:18,620 What am I doing here? 397 00:28:18,620 --> 00:28:22,970 So we're looping through every single parameter type that is required for this function. 398 00:28:22,970 --> 00:28:29,630 And we're setting arg to be added to either, uh, any of these things based on whether or not we require 399 00:28:29,630 --> 00:28:35,570 player A number or a string, or if it's not any of that, then we just set it to itself, and then 400 00:28:35,570 --> 00:28:42,170 we're checking to ensure that this argument that needs to be added is actually the expected type that 401 00:28:42,170 --> 00:28:44,270 we need for this particular command. 402 00:28:44,270 --> 00:28:47,000 So we got to make sure it equals this parameter type. 403 00:28:47,000 --> 00:28:51,980 The thing we just got, if it isn't then we're going to tell them we didn't get the correct argument 404 00:28:51,980 --> 00:28:55,400 for the parameter that we need in our function. 405 00:28:55,400 --> 00:29:01,880 So we're going to tell them like command set speed expected number for argument number three. 406 00:29:01,880 --> 00:29:05,450 But we got a string instead as an example. 407 00:29:05,600 --> 00:29:11,600 So these checks here help to ensure that these commands are getting the correct arguments passed to 408 00:29:11,600 --> 00:29:12,230 them. 409 00:29:12,230 --> 00:29:17,360 Because if they don't well our commands are going to error and we don't want that to happen. 410 00:29:17,840 --> 00:29:25,070 Otherwise, if we make it past all of these checks and everything is good, then we can use table.insert 411 00:29:25,070 --> 00:29:30,740 inside of our args to pass table and insert arg to be added. 412 00:29:31,010 --> 00:29:36,920 And then once we're finally done looping through all the required parameters for this particular command, 413 00:29:36,920 --> 00:29:44,780 then we can use our command and use the callback function inside of it, and pass the player that wants 414 00:29:44,780 --> 00:29:46,040 to execute the command. 415 00:29:46,040 --> 00:29:52,520 And then all of the arguments we need to pass, and we can use the unpack function here and pass args 416 00:29:52,520 --> 00:29:53,330 to pass. 417 00:29:53,330 --> 00:29:58,850 And what this does is it's going to split up every single argument in our table to be, uh, separate 418 00:29:58,850 --> 00:30:00,410 arguments to the function. 419 00:30:00,410 --> 00:30:06,530 So if there is three different arguments in here, then it would split it up like, you know, as three 420 00:30:06,530 --> 00:30:09,920 different arguments being passed to the function and not in a table. 421 00:30:10,510 --> 00:30:13,690 So unpack args to pass. 422 00:30:13,690 --> 00:30:19,420 And since we expect that this callback function is going to return back to us a boolean and a string, 423 00:30:19,420 --> 00:30:24,550 we'll call it success and the result from this function. 424 00:30:24,820 --> 00:30:32,290 If we were somehow not successful in executing this function, so if not success, then we're going 425 00:30:32,290 --> 00:30:33,700 to return false. 426 00:30:33,700 --> 00:30:37,900 And again give them a message like the command. 427 00:30:37,900 --> 00:30:41,980 And we're going to put a directive in here. 428 00:30:43,160 --> 00:30:46,940 The command encountered a problem. 429 00:30:49,540 --> 00:30:51,070 During execution. 430 00:30:51,070 --> 00:30:57,100 And the problem is we'll put another directive here to say the problem is this. 431 00:30:58,200 --> 00:31:05,730 We're going to format this with the command dot name and then the result from our callback function. 432 00:31:06,290 --> 00:31:12,620 So if somehow any of our commands encounter a problem, then we're going to tell the person who executed 433 00:31:12,620 --> 00:31:18,500 the function or the command that, hey, this command encountered a problem, and the problem was this. 434 00:31:18,500 --> 00:31:21,710 And that's going to be told to us from our callback function. 435 00:31:22,450 --> 00:31:24,850 Otherwise we just return true here. 436 00:31:24,850 --> 00:31:27,310 Meaning that we executed successfully. 437 00:31:27,610 --> 00:31:27,940 All right. 438 00:31:27,940 --> 00:31:30,640 So now let's set up our remove admin from function. 439 00:31:30,640 --> 00:31:32,680 This one should be fairly straightforward. 440 00:31:32,680 --> 00:31:36,550 First we need to create a variable as the key for this player. 441 00:31:36,550 --> 00:31:37,750 So two string. 442 00:31:37,750 --> 00:31:40,030 And we're going to get the players dot user ID. 443 00:31:41,170 --> 00:31:49,000 And we're going to check if this player has a key value pair within our connections table first of all. 444 00:31:49,000 --> 00:31:55,870 So if they exist in here then what we need to do is we need to access that connection they have in there, 445 00:31:55,870 --> 00:31:57,940 which would be connected to their chatted event. 446 00:31:57,940 --> 00:32:00,070 And we need to disconnect that. 447 00:32:00,920 --> 00:32:06,200 And then we can set their connections key value pair equal to nil. 448 00:32:06,200 --> 00:32:08,150 So equal to nil. 449 00:32:08,150 --> 00:32:09,050 And that's it. 450 00:32:09,670 --> 00:32:13,150 And then we need to check if they have a guy on them. 451 00:32:13,150 --> 00:32:22,690 So if player dot player guy then we're going to find first child admin guy. 452 00:32:22,720 --> 00:32:24,340 That's the name of our guy. 453 00:32:24,340 --> 00:32:28,570 And if they have this guy then we're just going to destroy it. 454 00:32:30,180 --> 00:32:30,540 All right. 455 00:32:30,540 --> 00:32:33,330 And I'm pretty sure that's all we need to do for that function. 456 00:32:33,360 --> 00:32:33,840 All right. 457 00:32:33,840 --> 00:32:36,900 So now let's go ahead and set up our setup admin for function. 458 00:32:36,900 --> 00:32:42,780 So first we need to check if our player is an admin if they aren't. 459 00:32:42,780 --> 00:32:47,880 So if their rank is equal to admin enum dot non-admin. 460 00:32:48,390 --> 00:32:53,340 Well then we just need to return out of this function and not do anything because we don't care about 461 00:32:53,340 --> 00:32:54,030 this player. 462 00:32:54,480 --> 00:33:01,830 Otherwise, if they do have admin, then what we need to do is first we need to remove admin from this 463 00:33:01,830 --> 00:33:03,450 player or aka. 464 00:33:03,450 --> 00:33:10,830 We need to disconnect any previous charted events and destroy any guys in their player guy folder in 465 00:33:10,830 --> 00:33:11,880 case they have it. 466 00:33:11,880 --> 00:33:17,880 So this is for like when you have a moderator in your game and you want to promote them to administrator, 467 00:33:17,880 --> 00:33:21,870 well, they need to re-update their roles and re-update their guy. 468 00:33:21,870 --> 00:33:25,230 So we need to destroy their old ones and then give them new ones. 469 00:33:25,800 --> 00:33:28,260 So we're going to remove admin from this player. 470 00:33:28,350 --> 00:33:34,710 And then what we could do is inside our connections table, we can use the two string function and get 471 00:33:34,710 --> 00:33:35,910 their player dot user ID. 472 00:33:35,910 --> 00:33:37,410 So this is their key again. 473 00:33:37,410 --> 00:33:41,820 And we're going to set it equal to player dot chatted. 474 00:33:42,090 --> 00:33:45,600 There's that event and we're going to connect a function to this. 475 00:33:45,870 --> 00:33:49,500 And when they chat they're going to give us a message that they chatted. 476 00:33:49,500 --> 00:33:55,860 And we're going to execute this command so we can do success. 477 00:33:55,860 --> 00:33:58,440 And result is equal to execute command. 478 00:33:58,440 --> 00:34:01,080 And we're going to pass the player and the message. 479 00:34:01,780 --> 00:34:04,420 And if we were not successful in executing this command. 480 00:34:05,140 --> 00:34:08,560 Then we need to tell this player that something went wrong. 481 00:34:08,560 --> 00:34:14,080 And there's actually a frame inside of our admin GUI, like I showed in the previous lecture, that 482 00:34:14,080 --> 00:34:15,640 we can display a message to them. 483 00:34:15,640 --> 00:34:20,110 So that's what we're going to use the comms event for, is that we're going to fire to this client, 484 00:34:20,110 --> 00:34:24,640 this player, and we're going to tell them to do an action like display a message. 485 00:34:24,640 --> 00:34:30,910 So display message and the message is going to be the result from our execute command function. 486 00:34:30,910 --> 00:34:35,530 So it's going to tell them exactly what went wrong when they were trying to execute the function. 487 00:34:35,890 --> 00:34:38,830 And once we've got that done we need to give the player a GUI. 488 00:34:38,860 --> 00:34:43,990 So I'm going to create a clone of IT admin GUI clone. 489 00:34:43,990 --> 00:34:49,960 And we're going to set the clone dot parent equal to this players dot player GUI folder. 490 00:34:50,780 --> 00:34:51,470 Alrighty. 491 00:34:51,470 --> 00:34:54,710 The next thing we need to do is fill out our event handlers. 492 00:34:54,710 --> 00:34:57,290 So what do we want to do when a player gets added to our game? 493 00:34:57,320 --> 00:35:02,660 Well, first we want to get their key or a.k.a their user ID as a string. 494 00:35:02,660 --> 00:35:05,210 So two string player dot user ID. 495 00:35:05,780 --> 00:35:11,870 Now the first thing I want to check actually is to see if they exist within our server bans table within 496 00:35:11,870 --> 00:35:13,760 our settings module script. 497 00:35:13,760 --> 00:35:23,180 So if inside of admin settings not admin assets, admin settings, dot server bans and we pass this 498 00:35:23,180 --> 00:35:28,250 key in there, if their user ID is in there, then we need to kick them because they're banned. 499 00:35:28,250 --> 00:35:28,670 Right. 500 00:35:28,670 --> 00:35:34,070 So we can do player kick and we'll give them a message. 501 00:35:34,070 --> 00:35:39,680 And actually what we're going to do is when we create our ban command, we're going to store the message 502 00:35:39,680 --> 00:35:43,970 of whoever banned them forever for the duration of the server's lifetime. 503 00:35:43,970 --> 00:35:47,330 And we're actually going to store it inside of our server bans table. 504 00:35:47,330 --> 00:35:52,730 So if we ban a player, then we'll have a key that's their user ID like this. 505 00:35:52,730 --> 00:35:59,060 And what's going to be assigned to that key is a message like you are banned because of some reason, 506 00:35:59,060 --> 00:35:59,510 right? 507 00:36:00,400 --> 00:36:05,470 So what we could do is we could just pass admin settings. 508 00:36:06,200 --> 00:36:11,450 Dot server bands and get the value that is stored at this key, which should be a string. 509 00:36:11,570 --> 00:36:17,840 Otherwise, if they're not band, then we can call the setup admin for function and pass the player. 510 00:36:17,840 --> 00:36:21,710 So every single player that joins our game, we're going to check whether or not they're an admin. 511 00:36:21,710 --> 00:36:24,020 And if they are we need to set up admin for them. 512 00:36:24,410 --> 00:36:24,920 Okay. 513 00:36:24,920 --> 00:36:28,370 I'm pretty sure that's all we need to do for this particular event. 514 00:36:28,370 --> 00:36:34,340 The next thing we should fill out is our on server invoke function for our request remote function. 515 00:36:34,700 --> 00:36:42,440 Now there's really only a couple of things that I anticipate the player to request from the server. 516 00:36:42,440 --> 00:36:47,150 One of the actions is going to be to execute a command. 517 00:36:47,150 --> 00:36:51,440 So this is specifically for when they're using the GUI on their screen. 518 00:36:51,440 --> 00:36:54,050 They're using that command line to execute a command. 519 00:36:54,050 --> 00:36:59,630 They're not going to be doing it through the chat event, but instead they're going to be doing it through 520 00:36:59,630 --> 00:37:00,650 their GUI. 521 00:37:00,650 --> 00:37:01,280 Right? 522 00:37:01,280 --> 00:37:04,760 So they're going to request to the server to execute a command. 523 00:37:05,300 --> 00:37:09,710 And we can basically just do the exact same thing that we did for when a player chats. 524 00:37:09,740 --> 00:37:10,340 Right. 525 00:37:10,490 --> 00:37:15,440 Another action that I expect for them to do is to get their rank. 526 00:37:15,440 --> 00:37:19,640 So if their action is equal to get rank, then we'll just supply the rank to them. 527 00:37:20,120 --> 00:37:23,960 And this is because players can't access the data store on the client. 528 00:37:23,960 --> 00:37:27,830 So at any time when the player requests to get their rank, then we're just going to give it to them. 529 00:37:28,310 --> 00:37:33,350 Now before we actually start executing and stuff in here, we need to first verify that the arguments 530 00:37:33,350 --> 00:37:37,520 that the player has given to this, uh, remote function is correct. 531 00:37:38,030 --> 00:37:42,590 So what I can do is I'm going to create a variable called result, and we're going to set it equal to 532 00:37:42,590 --> 00:37:44,180 the check arg for type. 533 00:37:44,180 --> 00:37:46,460 And the argument is going to be our action. 534 00:37:46,460 --> 00:37:48,350 And we want to make sure that it's a string. 535 00:37:50,820 --> 00:37:52,380 If it's not a string. 536 00:37:52,380 --> 00:37:57,330 So if not result, then we're going to return the result, which is going to be false. 537 00:37:57,330 --> 00:38:09,390 And we're going to tell them that action of type put a directive here did not match expected type string. 538 00:38:09,390 --> 00:38:12,960 And actually we can put this in little quotation marks. 539 00:38:14,740 --> 00:38:20,200 And then we'll call the format function on this and pass the type of the action they pass. 540 00:38:21,200 --> 00:38:27,560 So if an exploiter decides to be a little stupid and spam our remote functions with arguments that do 541 00:38:27,560 --> 00:38:33,650 not match what we expect, then we're just going to tell them to shove it, go away, or basically just 542 00:38:33,650 --> 00:38:34,130 go away. 543 00:38:34,130 --> 00:38:35,030 We don't care. 544 00:38:35,120 --> 00:38:38,510 Again, this is to make sure that your remotes are protected. 545 00:38:38,510 --> 00:38:42,110 We always want to protect our remote functions and our remote events. 546 00:38:42,350 --> 00:38:45,800 Otherwise, if that's good, then what we could do is we could fill out this section right here. 547 00:38:45,800 --> 00:38:50,180 And I'm going to override result again with our check ARG for type. 548 00:38:50,180 --> 00:38:57,650 And this time I want to make sure the argument they're passing in within our table is a string. 549 00:38:57,650 --> 00:39:03,320 And that's the other thing actually, because we need to also verify that args is a table. 550 00:39:03,320 --> 00:39:05,390 So we can do the same thing here. 551 00:39:05,390 --> 00:39:08,990 Result equal to check arg for type args. 552 00:39:08,990 --> 00:39:10,760 And we got to make sure it's a table. 553 00:39:11,240 --> 00:39:14,540 If not results then we'll return results. 554 00:39:16,270 --> 00:39:21,130 Expected table for arguments. 555 00:39:21,130 --> 00:39:22,120 We'll just do that. 556 00:39:23,130 --> 00:39:28,110 And then inside of here, we need to verify the contents inside of the table. 557 00:39:28,140 --> 00:39:34,380 So basically whenever a player requests or uses this remote function, the only thing that should be 558 00:39:34,380 --> 00:39:39,600 inside of this table is a string or aka their message or command. 559 00:39:39,600 --> 00:39:40,230 Right? 560 00:39:40,230 --> 00:39:43,800 The string should be something like kill, blah blah blah, whatever. 561 00:39:43,800 --> 00:39:48,330 That should be the value inside of our table if it isn't for some reason. 562 00:39:48,330 --> 00:39:54,750 So again, this is exploiters manipulating your remote functions and we're going to return false again 563 00:39:54,750 --> 00:39:56,670 or aka the results. 564 00:39:57,510 --> 00:40:00,120 And we're going to tell them that. 565 00:40:00,860 --> 00:40:09,260 Argument one of type and we can just put a colon s here did not match expected type string. 566 00:40:09,870 --> 00:40:16,800 And we can format this with the type of our args one. 567 00:40:17,830 --> 00:40:19,390 And then put your end statement. 568 00:40:19,840 --> 00:40:24,880 Otherwise, if that checks out, then we can just return the result from our execute command function. 569 00:40:24,880 --> 00:40:28,840 So we're going to pass the player and then their message which is args one. 570 00:40:29,630 --> 00:40:33,950 So we can actually make a note here args one should be a string. 571 00:40:34,690 --> 00:40:37,330 And then for the git rank, this one's pretty easy. 572 00:40:37,360 --> 00:40:42,700 We just need to return the value that is returned from our git ranked function. 573 00:40:44,930 --> 00:40:49,970 And then if the action that the player requests doesn't match any of the ones that we have in here, 574 00:40:49,970 --> 00:41:01,310 we're just going to return false and tell them, uh re requested action, put a directive did not match 575 00:41:01,310 --> 00:41:04,340 any of the possible actions. 576 00:41:04,340 --> 00:41:10,580 And again we're going to format this with the action that they passed to the server. 577 00:41:11,520 --> 00:41:13,170 Okay, we're almost finished here. 578 00:41:13,170 --> 00:41:17,400 The last thing we need to do is fill out this, and we're not going to fill it out completely yet, 579 00:41:17,400 --> 00:41:24,390 because the purpose of this bindable here is mainly for when we're executing different commands. 580 00:41:24,390 --> 00:41:31,590 So if we have commands in here, like to mod someone or set them or give them admin or give them permanent 581 00:41:31,590 --> 00:41:35,700 admin or moderator, then we need to specifically do that from this script. 582 00:41:35,700 --> 00:41:41,010 And that means this module script is going to request to this server script. 583 00:41:41,010 --> 00:41:45,540 Hey, can you please set the admin or permanent admin for this player? 584 00:41:45,540 --> 00:41:48,300 And that's the purpose of this Bindable. 585 00:41:48,300 --> 00:41:55,320 So we can give some actions like if action is equal to uh, set temporary privileges. 586 00:41:56,520 --> 00:41:59,130 Then we'll do that functionality in there. 587 00:41:59,760 --> 00:42:03,270 If the action is to set permanent privileges. 588 00:42:04,470 --> 00:42:06,960 Then we'll do the functionality in there. 589 00:42:08,030 --> 00:42:12,800 Otherwise if the action is to remove privileges. 590 00:42:14,470 --> 00:42:16,480 Then we'll do it in there. 591 00:42:17,150 --> 00:42:17,690 Otherwise. 592 00:42:17,690 --> 00:42:23,450 If the action is to get the rank of a player, we'll do a get rank action. 593 00:42:24,790 --> 00:42:31,000 Then we can, you know, just return git rank args one, which should be a player. 594 00:42:31,990 --> 00:42:39,910 Otherwise we'll just return false and say requested action did not match any of the possible actions. 595 00:42:39,910 --> 00:42:40,720 Whatever. 596 00:42:40,780 --> 00:42:44,530 Or we can actually just copy the exact same error message that we gave here. 597 00:42:47,030 --> 00:42:48,980 So we're not going to fill out these just yet. 598 00:42:48,980 --> 00:42:54,740 We're going to fill out those later when we actually create our different, uh, admin commands for 599 00:42:54,740 --> 00:42:55,970 our admin system. 600 00:42:56,420 --> 00:43:01,010 Other than that, our admin handler for the most part is complete. 601 00:43:01,010 --> 00:43:05,090 And the next lecture we're going to start scripting our GUI on the client. 602 00:43:05,090 --> 00:43:06,770 So I'll go ahead and see you there.